package com.test.rm.service.impl;

import com.test.rm.mapper.TccMapper;
import com.test.rm.service.TccService;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Service
public class TccServiceImpl implements TccService {

    @Autowired
    private TccMapper tccMapper;

    AtomicInteger ai = new AtomicInteger(0);

    /**
     * tcc服务t（try）方法
     * 根据实际业务场景选择实际业务执行逻辑或者资源预留逻辑
     *
     * @param params - name
     * @return String
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public String insert(BusinessActionContext context, Map<String, String> params) {
        log.info("xid = " + RootContext.getXID());
        //实际的操作
        tccMapper.insert(params);
        context.getActionContext().put("params", params);

        if(ai.getAndIncrement()%3==0){
            throw new RuntimeException("rm: " + RootContext.getXID());
        }
        return "success";
    }

    /**
     * tcc服务 confirm方法
     * 若一阶段采用资源预留，在二阶段确认时要提交预留的资源
     *
     * @param context 上下文
     * @return boolean
     */
    @Override
    public boolean commit(BusinessActionContext context) {
        log.info("xid = " + context.getXid() + "提交成功");
        // 若一阶段资源预留，这里则要提交资源
        return true;
    }

    /**
     * tcc 服务 cancel方法
     *
     * @param context 上下文
     * @return boolean
     */
    @Override
    public boolean rollback(BusinessActionContext context) {
        log.info("xid = " + context.getXid() + "提交失败");
        Map<String, String> params = (Map<String, String>) context.getActionContext().get("params");
        tccMapper.delete(params);
        // 回滚操作
        return true;
    }
}
